import xlrd
from django.shortcuts import render
import time
import logging
import json
import requests
from weixin.api.verify_account import base64_api, get_information
from lxml import etree
from django.core import serializers
from django.core.exceptions import ObjectDoesNotExist
from django.db import transaction
from django.db.models import Q
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

from blueapps.core.exceptions import DatabaseError
from course.models import Course, Member, UserCourseContact
from question.models import Question

# Create your views here.
logger = logging.getLogger("root")


def is_teacher(fun):
    def inner(request, *args, **kwargs):
        try:
            user_id = request.user.id
            identity = Member.objects.filter(id=user_id).values(
                "identity"
            )  # 取出数据表中的identity值
            if (
                    identity.first()["identity"] == Member.Identity.TEACHER
            ):  # 将取出的Queryset转化为字典与字符串比较
                return fun(request, *args, **kwargs)
            else:
                return JsonResponse(
                    {"result": False, "code": 403, "message": "您没有操作权限！", "data": []}
                )
        except ObjectDoesNotExist:
            return JsonResponse(
                {"result": False, "code": 401, "message": "请求错误！用户id不存在", "data": []}
            )  # 返回信息

    return inner


@is_teacher
def manage_course(request):
    # 增
    if request.method == "POST":
        req = json.loads(request.body)
        course_name = req.get("course_name")  # 想创建的课程名称
        teacher = req.get("teacher")
        course_introduction = req.get("course_introduction")  # 课程简介
        manage_student = req.get("manage_student")  # 学生管理员
        try:
            news_course_info = Course.objects.create(
                course_name=course_name,
                course_introduction=course_introduction,
                teacher=teacher,
                create_people="{0}({1})".format(request.user.class_number, request.user.name),
                manage_student=manage_student,
            )  # 将得到的数据加到course表
            UserCourseContact.objects.create(user_id=request.user.id, course_id=news_course_info.id)
            return JsonResponse(
                {"result": True, "message": "增加成功", "code": 201, "data": []},
                json_dumps_params={"ensure_ascii": False},
            )
        except DatabaseError as e:
            logger.exception(e)
            return JsonResponse(
                {"result": True, "message": "增加失败，请检查您输入的信息或者身份信息是否完善", "code": 412, "data": []},
                json_dumps_params={"ensure_ascii": False},
            )

    # 删
    if request.method == "DELETE":
        course_id = request.GET.get("course_id")
        if not course_id:
            return JsonResponse(
                {"result": False, "message": "删除失败！课程id不能为空", "code": 400, "data": []},
                json_dumps_params={"ensure_ascii": False},
            )
        try:
            with transaction.atomic():
                Course.objects.get(
                    Q(id=course_id) & (Q(create_people="{0}({1})".format(request.user.class_number, request.user.name))
                                       | Q(
                                teacher="{0}({1})".format(request.user.class_number, request.user.name)))).delete()
                UserCourseContact.objects.filter(course_id=course_id).delete()
                return JsonResponse(
                    {"result": True, "message": "删除成功", "code": 200, "data": []},
                    json_dumps_params={"ensure_ascii": False},
                )
        except ObjectDoesNotExist as e:
            logger.exception(e)
            return JsonResponse(
                {
                    "result": False,
                    "message": "删除失败！",
                    "code": 412,
                    "data": [],
                },
                json_dumps_params={"ensure_ascii": False},
            )

    # 改
    if request.method == "PUT":
        req = json.loads(request.body)
        course_id = req.get("course_id")
        if not course_id:
            return JsonResponse(
                {"result": False, "message": "修改失败！课程id不能为空", "code": 400, "data": []},
                json_dumps_params={"ensure_ascii": False},
            )
        try:
            course = Course.objects.get(
                Q(id=course_id) & (Q(create_people="{0}({1})".format(request.user.class_number, request.user.name))
                                   | Q(teacher="{0}({1})".format(request.user.class_number, request.user.name))))
            course.course_name = req.get("course_name", course.course_name)
            course.course_introduction = req.get(
                "course_introduction", course.course_introduction
            )
            course.teacher = req.get("teacher", course.teacher)
            course.manage_student = req.get("manage_student", course.manage_student)
            course.save()
            return JsonResponse(
                {"result": True, "message": "修改成功", "code": 200, "data": []},
                json_dumps_params={"ensure_ascii": False},
            )
        except DatabaseError as e:
            logger.exception(e)
            return JsonResponse(
                {
                    "result": False,
                    "message": "修改失败",
                    "code": 412,
                    "data": [],
                },
                json_dumps_params={"ensure_ascii": False},
            )


# 查
def search_courses_by_userid(request):
    if request.method == "GET":
        user_id = request.user.id
        course_ids = UserCourseContact.objects.filter(user_id=user_id).values_list(
            "course_id", flat=True
        )
        course = Course.objects.in_bulk(course_ids).values()
        courses = serializers.serialize(
            "json", course, ensure_ascii=False
        )
        return JsonResponse(
            {
                "result": True,
                "message": "查询成功",
                "code": 200,
                "data": courses,
            },
            json_dumps_params={"ensure_ascii": False},
        )


def identify_user(username, password):
    global base_url

    base_url = "http://202.200.112.200/"
    headers = {
        'User-Agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 '
            'Safari/537.36',
        'Accept':
            'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    }

    login_url = base_url
    res = requests.get(login_url, allow_redirects=False)
    login_url = login_url + res.headers['location']
    login_url = login_url.replace('Default', 'default2')
    login_url = login_url.replace(r'/(', '(')
    checkcode_url = login_url.replace(r'/default2.aspx', r'/CheckCode.aspx?')
    base_url = login_url.replace(r'/default2.aspx', r'/')

    cookies = res.cookies
    checkcode = requests.get(checkcode_url, cookies=cookies, headers=headers)  # 伪装成浏览器
    code = base64_api(checkcode.content)
    post_data = {
        '__VIEWSTATE': 'dDwtNTE2MjI4MTQ7Oz4v9xUqkOgkwu+22N3B4gSg7V/qCg==',
        'txtUserName': username,
        'Textbox1': '',
        'TextBox2': password,
        'txtSecretCode': code,
        'RadioButtonList1': '学生'.encode("gb2312"),
        'Button1': '',
        'lbLanguage': '',
        'hidPdrs': '',
        'hidsc': '',
    }
    resource = requests.post(url=login_url,
                             data=post_data,
                             cookies=cookies,
                             headers=headers).text

    if '活动报名' in resource:
        dom_tree = etree.HTML(resource)
        name_info = dom_tree.xpath('//span[@id="xhxm"]/text()')
        name = name_info[0].split('同')[0]
        index = name_info[0].index("同")
        identify_str = name_info[0][index:]
        user_info = get_information(cookies, username, name)
        return 1, user_info, identify_str
    else:
        if '密码错误' in resource:
            return 2, None
        else:
            if '用户名不存在':
                return 3, None


def get_info(request):
    req = json.loads(request.body)
    # username = request.POST.get("username")
    # password = request.POST.get("password")
    username = req.get("username")
    password = req.get("password")
    status, user_info_list, identify_str = identify_user(username, password)
    if status == "1":
        user_info = Member.objects.get(id=request.user.id)
        user_info.class_number = user_info_list.get("user_name")
        user_info.name = user_info_list.get("user_real_name")
        user_info.gender = user_info_list.get("user_sex")
        user_info.college = user_info_list.get("user_college")
        user_info.professional_class = user_info_list.get("user_class")
        if identify_str == "同学":
            user_info.identity = "STUDENT"
            user_info.save()
        else:
            user_info.identity = "TEACHER"
            user_info.save()
        return JsonResponse(
            {"result": True, "code": 0, "data": [], "message": "用户身份认证成功"},
            json_dumps_params={"ensure_ascii": False},
        )
    elif status == "2":
        return JsonResponse(
            {"result": True, "code": 0, "data": [], "message": "用户身份认证失败，密码错误"},
            json_dumps_params={"ensure_ascii": False},
        )
    elif status == "3":
        return JsonResponse(
            {"result": True, "code": 0, "data": [], "message": "用户身份认证失败，账号不存在"},
            json_dumps_params={"ensure_ascii": False},
        )


@csrf_exempt
def get_excel_manage(request):
    excel_files = request.FILES.get("excel_file")
    suffix = excel_files.name.split(".")[-1]
    course_id = request.POST.get("course_id")
    if suffix == "xls":
        data = xlrd.open_workbook(
            filename=None, file_contents=excel_files.read(), formatting_info=True
        )
    elif suffix == "xlsx":
        data = xlrd.open_workbook(filename=None, file_contents=excel_files.read())
    else:
        return JsonResponse(
            {
                "result": False,
                "message": "导入文件错误，请检查导入文件是否为excel格式",
                "code": 406,
                "data": [],
            },
            json_dumps_params={"ensure_ascii": False},
        )
    tables = data.sheets()
    row_sign = 0
    err_sign = 0
    values_1 = []
    for table in tables:
        rows = table.nrows
        values_0 = table.row_values(0)
        if rows != 1:
            values_1 = table.row_values(1)
        try:
            if values_0[0] == "教学班点名册" and values_1[0] == "学年" and values_1[1] == "2021-2022":
                with transaction.atomic():
                    for row in range(4, rows):
                        row_values = table.row_values(row)
                        err_sign = (row + 1)
                        Member.objects.update_or_create(
                            class_number=row_values[0],  # 学号
                            name=row_values[2],  # 姓名
                            professional_class=row_values[4],  # 班级
                        )
                        row_sign = row_sign + 1
                return JsonResponse(
                    {
                        "result": True,
                        "message": "导入成功",
                        "code": 200,
                        "data": [],
                    },
                    json_dumps_params={"ensure_ascii": False},
                )
            elif values_0[0] == "questType" and values_0[1] == "questTitle":
                course = Course.objects.get(id=course_id)
                for row in range(1, rows):
                    row_values = table.row_values(row)
                    err_sign = (row + 1)
                    if not row_values[0]:
                        return JsonResponse(
                            {
                                "result": True,
                                "message": "导入成功,共导入{0}行".format(row_sign),
                                "code": 200,
                                "data": [],
                            },
                            json_dumps_params={"ensure_ascii": False},
                        )
                    if row_values[0] == 1.0:
                        with transaction.atomic():
                            obj, create = Question.objects.update_or_create(
                                question_type=row_values[0],  # 问题类型
                                question_title=row_values[1],  # 问题内容
                                question_optionA=row_values[2],  # 选项A
                                question_optionB=row_values[3],
                                question_optionC=row_values[4],
                                question_optionD=row_values[5],
                                question_answer=row_values[6],  # 问题答案
                                question_chapter=row_values[7],  # 问题科目
                                course=course
                            )
                        if create:
                            row_sign = row_sign + 1
                    elif row_values[0] == 2.0:
                        with transaction.atomic():
                            obj, create = Question.objects.update_or_create(
                                question_type=row_values[0],
                                question_title=row_values[1],
                                question_answer=row_values[2],
                                question_chapter=row_values[3],
                                course=course
                            )
                        if create:
                            row_sign = row_sign + 1
                    else:
                        return JsonResponse(
                            {
                                "result": False,
                                "message": "所导入的问题的类型不正确！错误行{0}".format(err_sign),
                                "code": 406,
                                "data": [],
                            },
                            json_dumps_params={"ensure_ascii": False},
                        )
                return JsonResponse(
                    {
                        "result": True,
                        "message": "导入成功,共导入{0}行,数据库中可能含有您导入的题目，重复题目已经跳过或更新,也可能是您的excel表为空".format(row_sign),
                        "code": 200,
                        "data": [],
                    },
                    json_dumps_params={"ensure_ascii": False},
                )
            else:
                return JsonResponse(
                    {
                        "result": False,
                        "message": "所导入的excel的格式不正确！",
                        "code": 406,
                        "data": [],
                    },
                    json_dumps_params={"ensure_ascii": False},
                )
        except DatabaseError:
            return JsonResponse(
                {
                    "result": False,
                    "message": "解析excel文件或者数据插入错误，请检查你excel的字段与数据库是否一致，或必填字段是否为空,错误行为:[]".format(err_sign),
                    "code": 200,
                    "data": [],
                },
                json_dumps_params={"ensure_ascii": False},
            )


def excel(request):
    return render(request, "测试excel.html")


def get_user_info(request):
    """
    @api {GET} /account/get_user_info/ 获取用户信息
    @apiName GetUserInfo
    @apiGroup User
    """
    if request.method == "GET":
        member = request.user
        return JsonResponse(
            {
                "result": True,
                "code": 200,
                "data": {
                    "id": member.id,
                    "username": member.username,
                    "timestamp": time.time(),
                    "class_number": member.class_number,
                    "name": member.name,
                    # "affiliated_college": member.affiliated_college,
                    "professional_class": member.professional_class,
                    "gender": member.gender,
                    "identity": member.identity,
                    "phone_number": member.phone_number,
                    "email_number": member.email_number,
                    "qq_number": member.qq_number,
                    "wechat_number": member.wechat_number,
                },
                "message": "获取用户信息成功",
            },
            json_dumps_params={"ensure_ascii": False}
        )
    else:
        return JsonResponse(
            {"result": False, "code": 501, "data": {}, "message": "请求失败"},
            json_dumps_params={"ensure_ascii": False}
        )


def store_user_info(request):
    """
    @api {GET} /accountore_user_info/ 存储用户信息
    @apiName StoreUserInfo
    @apiGroup User
    """
    if request.method == "POST":
        user_id = request.user.id
        member = json.loads(request.body)
        get_user = Member.objects.get(id=user_id)
        try:
            get_user.phone_number = member.phone_number
            get_user.qq_number = member.qq_number
            get_user.email_number = member.email_number
            get_user.wechat_number = member.wechat_number
            get_user.save()
            return JsonResponse(
                {"result": True, "message": "增加成功", "code": 201, "data": []},
                json_dumps_params={"ensure_ascii": False},
            )
        except DatabaseError as e:
            return JsonResponse(
                {"result": True, "message": "增加失败，请检查您输入的信息", "code": 412, "data": []},
                json_dumps_params={"ensure_ascii": False},
            )


# 下拉显示老师名称列表
def search_teacher_names(request):
    if request.method == "GET":
        try:
            teacher_names = []
            teachers = Member.objects.filter(identity='TEACHER')
            for teacher in teachers:
                teacher_names.append("{0}({1})".format(teacher.class_number, teacher.name))
            return JsonResponse(
                {
                    "result": True,
                    "message": "显示成功",
                    "code": 200,
                    "data": json.dumps(teacher_names),
                },
                json_dumps_params={"ensure_ascii": False},
            )
        except DatabaseError as e:
            logger.exception(e)
            return JsonResponse(
                {
                    "result": False,
                    "message": "显示异常",
                    "code": 400,
                    "data": [],
                },
                json_dumps_params={"ensure_ascii": False},
            )
